/**
  此方法提交会超时
 * @param {number} n
 * @return {number}
 */
export var consecutiveNumbersSum = function (n) {
  if (n < 3) return 1
  let ans = 1
  let start = (n >> 1) + 1,
    end = (n >> 1) + 1
  while (start > 0) {
    const sum = getSum(start, end)
    if (sum === n) {
      ans++
      start -= 2
      end--
    } else if (sum > n) {
      end--
      start--
    } else {
      start--
    }
  }
  return ans
}

function getSum(start, end) {
  if (start === end) return start
  const n = end - start + 1
  if (n % 2 === 0) return (start + end) * (n / 2)
  return (start + end) * (n >> 1) + (start + end) / 2
}

/**
 假设我们存在某个连续段之和为 n，假定该连续段首项为 a，长度为 k，根据「等差数列求和」可知：

(a + a + k - 1) * k / 2 = n
--->
(2a + k - 1) * k = 2n
--->
2n >= k*k
 */
export var consecutiveNumbersSum2 = function (n) {
  let ans = 0
  const bound = 2 * n
  for (let k = 1; k * (k + 1) <= bound; k++) {
    if (isKConsecutive(n, k)) {
      ans++
    }
  }
  return ans
}

const isKConsecutive = (n, k) => {
  if (k % 2 === 1) {
    return n % k === 0
  } else {
    return n % k !== 0 && (2 * n) % k === 0
  }
}

/**
 * @param {number} n
 * @return {number}
 */
export var consecutiveNumbersSum3 = function (n) {
  /*
  第一个数： m
  长度： k >= 2
  sum = m + (m + 1) + (m + 2) + ... + (m + k - 1)
  化简得：2sum = k(2m + k - 1) = 2n
  需满足：
  1. 2n % k = 0
  2. (2n - k(k - 1)) % 2k = 0
 */
  let cnt = 1 // 自身就是一组
  const nn = 2 * n
  for (let k = 2; k < Math.sqrt(nn); k++) {
    if (nn % k === 0 && (nn - k * (k - 1)) % (2 * k) === 0) {
      cnt++
    }
  }
  return cnt
}
